#include "fatfs.h"
#include "log.h"
#include "stdbool.h"
#include "string.h"
static uint32_t totalsize = 0;
static uint32_t freesize = 0;

FIL openfile;
FATFS SDFatFs = {0};
char SD_Path[4]={0,0,0,0};

FATFS USBfatfs;
char UDisk_Path[4]={0,0,0,0};
extern Diskio_drvTypeDef  USBH_Driver;
uint8_t retSD; /* Return value for SD */

const char* DriverString[2]={
	{"USBDisk"},
  {"SDCard"}
};

//return 0:no sd card find 
//return 1: find sd card
uint8_t Fatfs_init(uint8_t driver)
{
	uint8_t res;
  FATFS *Fatfs;
  char *Path;
  Diskio_drvTypeDef *Driver;

  if(driver == SDCard)
  {
    Fatfs = &SDFatFs;
    Path = (char*)&SD_Path;
    Driver = &SD_Driver;
  }else if(driver == USBDisk)
  {
  //  Fatfs = &USBfatfs;
 //   Path = (char*)&UDisk_Path;
  //  Driver = &USBH_Driver;
  }
    /*## FatFS: Link the SD driver ###########################*/
    res = FATFS_LinkDriver(Driver, Path);
    if(res != FR_OK)
    {
      log_info("%s FATFS LinkDriver error",DriverString[driver]);
      return 0;
    }
    else{
      log_info("%s FATFS LinkDriver OK,Drive path is %s",DriverString[driver],Path);
    }
      /*##-2- Register the file system object to the FatFs module ##############*/
      log_info("%s FATFS mount",DriverString[driver]);
      res = f_mount(Fatfs, (TCHAR const*)Path, 0);
      if(res != FR_OK)
      {
        log_info("%s FATFS mount Error",DriverString[driver]);
        FATFS_UnLinkDriver(Path);
        return 0;
      }
      else{
        log_info("%s FATFS mount OK,Fatfs init done",DriverString[driver]);
      }
    res =  Fatfs_getfree(driver);//计算当时SD的容量跟剩余大小
    if(res != FR_OK)
    {
      log_info("%s FATFS get size Error",DriverString[driver]);
      return 0;
    }
    else{
      log_info("%s FATFS  total size is %d,free size is %d.",DriverString[driver],totalsize,freesize);
      return 1;
    }
}

 uint8_t Fatfs_getfree(uint8_t driver)
{
    uint8_t res;
    FATFS *fs1;
    uint32_t fre_clust=0, fre_sect=0, tot_sect=0;
 
   char *Path;

  if(driver == SDCard)
  {
    Path = (char*)&SD_Path;
  }else if(driver == USBDisk)
  {
    Path = (char*)&UDisk_Path;
  }

    //得到磁盘信息及空闲簇数量
    res =(uint32_t)f_getfree((const TCHAR*)Path, (DWORD*)&fre_clust, &fs1);
    if(res==0)
	{											   
	    tot_sect=(fs1->n_fatent-2)*fs1->csize;	//得到总扇区数
	    fre_sect=fre_clust*fs1->csize;			//得到空闲扇区数	   
#if _MAX_SS!=512				  				//扇区大小不是512字节,则转换为512字节
		tot_sect*=fs1->ssize/512;
		fre_sect*=fs1->ssize/512;
#endif	  
    totalsize=tot_sect>>1;	//单位为KB
		freesize=fre_sect>>1;	//单位为KB 
   }
   return res;
}

uint8_t Fatfs_open(uint8_t driver,uint8_t*path,uint8_t mode)
{
  char  filepath[50];
	memset(filepath,0,20);
  if(driver == SDCard)
  {
      strcat(filepath,SD_Path);
  }else if(driver == USBDisk)
  {
      strcat(filepath,UDisk_Path);
  }
  strcat((char*)filepath,(const char*)path);
  retSD=f_open(&openfile,(const TCHAR*)filepath,mode);//打开文件夹
  if(retSD != FR_OK)
    {
      log_info("FATFS open Error:%d",retSD);
    }
    else log_info("FATFS open file[%s] ok!",filepath);
  return retSD;
}

uint8_t Fatfs_close(void)
{
  retSD=f_close(&openfile);
	return retSD;
}

//读出数据
//len:读出的长度
//返回值:执行结果
uint8_t Fatfs_read(uint8_t *data,uint32_t len)
{
  uint16_t i;
  uint32_t tlen=0;
  uint32_t bytesread;
  uint8_t *pdata = data;
	for(i=0;i<len/512;i++)
	{
		retSD=f_read(&openfile,pdata,512,&bytesread);
		if(retSD)
		{
			log_info("Read Error:%d",retSD);
			break;
		}else
		{
			tlen+=bytesread;
      pdata += bytesread;
		}
	}
	if(len%512)
	{
		retSD=f_read(&openfile,pdata,len%512,&bytesread);
		if(retSD)	//读数据出错了
		{
			log_info("\r\nRead Error:%d",retSD);   
		}else
		{
			tlen+=bytesread;
		}	 
	}
	if(tlen)log_info("\r\nReaded data len:%d",tlen);//读到的数据长度
	log_info("Read data over");	 
	return retSD;
}

//写入数据
//data:数据缓存区
//len:写入长度
//返回值:执行结果
uint8_t Fatfs_write(uint8_t *data,uint32_t len)
{
  uint32_t byteswrite;  					   
  log_info("\r\nBegin Write file...");
  log_info("Write data len:%d",len);	 
    retSD=f_write(&openfile,data,len,&byteswrite);
    if(retSD)
    {
      log_info("Write Error:%d",retSD);   
    }else log_info("Writed data len:%d",byteswrite);
    log_info("Write data over.");
    return retSD;
}
